import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { BASE_API, defaultReqErrorMsg, tokenCookieKey } from '@/config'
import { useUserStore } from '@/stores/user'
import router from '@/router'
import Cookies from 'js-cookie'
import { Toast } from 'vant'

interface RequestConfig extends AxiosRequestConfig {
  /** 是否显示loading **/
  showLoading?: boolean
}

const instance = axios.create({
  baseURL: BASE_API,
  // 表示跨域请求时是否需要使用凭证
  withCredentials: false,
  // 请求超时时间
  timeout: 30000
})

class HttpService {
  private readonly http!: AxiosInstance
  // 当前showLoading的请求的数量，当值为0时才清除loading
  private loadingRequestNum: number

  constructor () {
    this.http = instance
    this.loadingRequestNum = 0

    // 添加拦截器
    this.addInterceptors(this.http)
  }

  request<T> (requestConfig: RequestConfig) {
    return new Promise<T>((resolve, reject) => {
      this.http.request(requestConfig)
        .then((response: AxiosResponse) => {
          resolve(response.data)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }

  private addInterceptors (http: AxiosInstance) {
    // 请求拦截器
    http.interceptors.request.use(
      (config: RequestConfig) => {
        const userStore = useUserStore()
        // 请求头加token
        if (userStore.token) {
          config.headers && (config.headers.authorization = userStore.token)
        }
        // 如果配置了showLoading, 显示loading状态
        if (config.showLoading) {
          this.addLoading()
        }
        return config
      }
    )

    // 响应拦截器
    http.interceptors.response.use(
      (response: AxiosResponse) => {
        // 如果配置了showLoading, 清除loading
        if (response.config && (response.config as RequestConfig).showLoading) {
          this.reduceLoading()
        }
        const res = response.data
        // 3906 没有登录
        if (res.status === 3906) {
          Toast('请先登录')
          // 重定向到登录页
          router.replace({ name: 'login', query: { redirect: router.currentRoute.value.fullPath } })
          return Promise.reject(res)
        }
        // 40004 token失效
        if (res.status === 40004) {
          Toast('登录状态过期，请重新登录')
          const userStore = useUserStore()
          // 清除token
          userStore.setToken('')
          Cookies.remove(tokenCookieKey)
          // 清除userStore.userInfo
          userStore.setUserInfo(null)
          // 重定向到登录页
          router.replace({ name: 'login', query: { redirect: router.currentRoute.value.fullPath } })
          return Promise.reject(res)
        }
        // 200 请求成功
        if (res.status === 200) {
          return Promise.resolve(response)
        } else if (res.message) {
          return Promise.reject(res)
        } else {
          return Promise.reject({ ...res, message: defaultReqErrorMsg })
        }
      },
      (error) => {
        // 清除loading
        if (error?.config?.showLoading) {
          this.reduceLoading()
        }
        if (error.message) {
          if (error.message.indexOf('timeout') > -1) {
            return Promise.reject({ message: '请求超时，请稍后再试', status: error?.response?.status, data: null })
          } else {
            return Promise.reject({ message: error.message, status: error?.response?.status, data: null })
          }
        }
        return Promise.reject({ message: defaultReqErrorMsg, status: error?.response?.status, data: null })
      }
    )
  }

  private addLoading () {
    this.loadingRequestNum++
    Toast.loading({
      duration: 0,
      forbidClick: true
    })
  }

  private reduceLoading () {
    this.loadingRequestNum--
    if (this.loadingRequestNum === 0) {
      Toast.clear()
    }
  }
}

const httpService = new HttpService()

export default httpService
